package org.example.config;

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.example.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        String requestURI = request.getRequestURI();
        log.debug("进入 JwtAuthenticationFilter，请求URI: {}", requestURI);
        
        // 排除不需要鉴权的路径
        if (requestURI.startsWith("/api/send-verify-code") || 
            requestURI.startsWith("/api/register") || 
            requestURI.startsWith("/api/login")) {
            log.debug("免鉴权路径，直接放行: {}", requestURI);
            filterChain.doFilter(request, response);
            log.debug("免鉴权路径处理完成: {}", requestURI);
            return;
        }
        
        // 获取请求头中的token
        String token = getTokenFromRequest(request);
        log.debug("获取到的token: {}", token);
        
        if (token == null) {
            log.warn("缺少认证令牌");
            sendErrorResponse(response, "缺少认证令牌");
            return;
        }
        
        try {
            // 验证token
            String username = jwtUtil.getUsernameFromToken(token);
            log.debug("从token中解析出用户名: {}", username);
            if (username != null && jwtUtil.validateToken(token, username)) {
                // 获取用户ID
                Long userId = jwtUtil.getUserIdFromToken(token);
                log.debug("从token中解析出用户ID: {}", userId);
                if (userId != null) {
                    // 将用户ID存储在请求属性中，方便Controller获取
                    request.setAttribute("userId", userId);
                }
                // 验证通过，继续处理请求
                log.debug("令牌验证通过，继续处理请求");
                filterChain.doFilter(request, response);
                log.debug("令牌验证通过，请求处理完成");
                return;
            } else {
                log.warn("令牌无效");
                sendErrorResponse(response, "令牌无效");
                return;
            }
        } catch (ExpiredJwtException e) {
            log.warn("令牌已过期: {}", e.getMessage());
            sendErrorResponse(response, "令牌已过期");
            return;
        } catch (UnsupportedJwtException e) {
            log.warn("不支持的令牌: {}", e.getMessage());
            sendErrorResponse(response, "不支持的令牌");
            return;
        } catch (MalformedJwtException e) {
            log.warn("令牌格式错误: {}", e.getMessage());
            sendErrorResponse(response, "令牌格式错误");
            return;
        } catch (SignatureException e) {
            log.warn("令牌签名错误: {}", e.getMessage());
            sendErrorResponse(response, "令牌签名错误");
            return;
        } catch (Exception e) {
            log.error("令牌验证异常: {}", e.getMessage());
            sendErrorResponse(response, "令牌验证异常");
            return;
        }
    }
    
    /**
     * 从请求头中获取token
     */
    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
    
    /**
     * 发送错误响应
     */
    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json;charset=UTF-8");
        
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", HttpServletResponse.SC_UNAUTHORIZED);
        errorResponse.put("message", message);
        
        response.getWriter().write("{\"code\": " + HttpServletResponse.SC_UNAUTHORIZED + ", \"message\": \"" + message + "\"}");
    }
}